package com.xyht.medicine_management_system.modules.medicineSource.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ResponseResult;
import com.xyht.medicine_management_system.modules.collect.entity.MmsMedicineCollect;
import com.xyht.medicine_management_system.modules.collect.mapper.MmsMedicineCollectMapper;
import com.xyht.medicine_management_system.modules.medicine.entity.MmsMedicine;
import com.xyht.medicine_management_system.modules.medicine.mapper.MmsMedicineMapper;
import com.xyht.medicine_management_system.modules.medicineSource.entity.MmsMedicineSource;
import com.xyht.medicine_management_system.modules.medicineSource.entity.MmsMedicineSourceClassification;
import com.xyht.medicine_management_system.modules.medicineSource.entity.MmsMedicineSourceMedicineRelation;
import com.xyht.medicine_management_system.modules.medicineSource.entity.req.MmsMedicineSourceReq;
import com.xyht.medicine_management_system.modules.medicineSource.entity.resp.*;
import com.xyht.medicine_management_system.modules.medicineSource.mapper.MmsMedicineSourceClassificationMapper;
import com.xyht.medicine_management_system.modules.medicineSource.mapper.MmsMedicineSourceMapper;
import com.xyht.medicine_management_system.modules.medicineSource.mapper.MmsMedicineSourceMedicineRelationMapper;
import com.xyht.medicine_management_system.modules.medicineSource.service.MmsMedicineSourceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.medicine_management_system.modules.medicineSource.util.MedicineSourceUtil;
import com.xyht.medicine_management_system.modules.user.entity.MmsUser;
import com.xyht.medicine_management_system.modules.user.entity.resp.UserinfoResp;
import com.xyht.medicine_management_system.modules.user.mapper.MmsUserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.medicine_management_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.medicine_management_system.modules.medicine.constant.MedicineCollectFlagConstant.MEDICINE_COLLECT;
import static com.xyht.medicine_management_system.modules.medicine.constant.MedicineCollectFlagConstant.MEDICINE_NOT_COLLECT;
import static com.xyht.medicine_management_system.modules.medicineSource.constant.IdTypeConstant.ID_TYPE_SOURCE;
import static com.xyht.medicine_management_system.modules.medicineSource.constant.IsDisplayConstant.IS_DISPLAY_FALSE;
import static com.xyht.medicine_management_system.modules.medicineSource.constant.IsDisplayConstant.IS_DISPLAY_TRUE;

/**
 * <p>
 * 药知源 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-11-26
 */
@Service
public class MmsMedicineSourceServiceImpl extends ServiceImpl<MmsMedicineSourceMapper, MmsMedicineSource> implements MmsMedicineSourceService {
    @Resource
    private MmsMedicineSourceMapper mmsMedicineSourceMapper;
    @Resource
    private MmsUserMapper mmsUserMapper;
    @Resource
    private MmsMedicineMapper mmsMedicineMapper;
    @Resource
    private MmsMedicineSourceMedicineRelationMapper mmsMedicineSourceMedicineRelationMapper;
    @Resource
    private MedicineSourceUtil medicineSourceUtil;
    @Resource
    private MmsMedicineCollectMapper medicineCollectMapper;
    @Resource
    private MmsMedicineSourceClassificationMapper mmsMedicineSourceClassificationMapper;

    @Override
    @Transactional
    public ResponseResult addMedicineSource(MmsMedicineSourceReq sourceReq, String user_id) {
        if (isNullOrEmpty(sourceReq.getSourceTitle(), sourceReq.getSourceAuthor(),
                sourceReq.getSourceContent(), sourceReq.getSourceImg(),
                sourceReq.getIsDisplay())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (!sourceReq.getIsDisplay().equals(IS_DISPLAY_FALSE) && !sourceReq.getIsDisplay().equals(IS_DISPLAY_TRUE)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (!isNullOrEmpty(sourceReq.getClassificationId())) {
            MmsMedicineSourceClassification mmsMedicineSourceClassification = mmsMedicineSourceClassificationMapper.selectById(sourceReq.getClassificationId());
            if (mmsMedicineSourceClassification == null) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_SOURCE_CLASSIFICATION_NOT_EXIST);
            }
        }

        MmsMedicineSource addSource = new MmsMedicineSource();
        BeanUtils.copyProperties(sourceReq, addSource);
        addSource.setSourceOperator(user_id);
        addSource.setLastUpdateUser(user_id);

        mmsMedicineSourceMapper.insert(addSource);
        String source_id = addSource.getId();

        if (sourceReq.getMedicineList() == null || sourceReq.getMedicineList().size() < 1) {
            return CommonResult.success();
        }

        for (String medicine_id : sourceReq.getMedicineList()) {
            MmsMedicine medicine = mmsMedicineMapper.selectById(medicine_id);
            if (medicine == null) {
                continue;
            }
            MmsMedicineSourceMedicineRelation addRelation = new MmsMedicineSourceMedicineRelation();
            addRelation.setSourceId(source_id);
            addRelation.setMedicineId(medicine_id);
            mmsMedicineSourceMedicineRelationMapper.insert(addRelation);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getMedicineSourceDetail(String sourceId, String userId) {
        MmsMedicineSource mmsMedicineSource = mmsMedicineSourceMapper.selectById(sourceId);
        if (mmsMedicineSource == null) {
            return CommonResult.failed(CommonCodeEnum.MEDICINE_SOURCE_NOT_EXIST);
        }

        MmsMedicineSourceResp medicineSourceResp = new MmsMedicineSourceResp();
        BeanUtils.copyProperties(mmsMedicineSource, medicineSourceResp);

        MmsUser sourceOperatorUser = mmsUserMapper.selectById(medicineSourceResp.getSourceOperator());
        if (sourceOperatorUser != null) {
            UserinfoResp userinfoResp = new UserinfoResp();
            BeanUtils.copyProperties(sourceOperatorUser, userinfoResp);
            medicineSourceResp.setOperatorUserinfo(userinfoResp);
        }

        MmsUser lastUser = mmsUserMapper.selectById(medicineSourceResp.getLastUpdateUser());
        if (lastUser != null) {
            UserinfoResp userinfoResp = new UserinfoResp();
            BeanUtils.copyProperties(lastUser, userinfoResp);
            medicineSourceResp.setLastUserinfo(userinfoResp);
        }

        if (!isNullOrEmpty(mmsMedicineSource.getClassificationId())) {
            MmsMedicineSourceClassification classification = mmsMedicineSourceClassificationMapper.selectById(mmsMedicineSource.getClassificationId());
            if (classification != null) {
                medicineSourceResp.setClassificationName(classification.getClassificationName());
            }
        }

        List<MmsMedicineSourceAndMedicineRelationResp> relationRespList = medicineSourceUtil.getRelationList(sourceId, ID_TYPE_SOURCE);
        medicineSourceResp.setRelationList(relationRespList);

        //收藏标识
        if (userId != null){
            List<MmsMedicineCollect> mmsMedicineCollects = medicineCollectMapper.selectList(new LambdaQueryWrapper<MmsMedicineCollect>()
                    .eq(MmsMedicineCollect::getCollectId, sourceId)
                    .eq(MmsMedicineCollect::getUserId, userId));
            if (mmsMedicineCollects.isEmpty()) {
                medicineSourceResp.setCollectFlag(MEDICINE_NOT_COLLECT);
            } else {
                medicineSourceResp.setCollectFlag(MEDICINE_COLLECT);
            }
        }
        return CommonResult.success(medicineSourceResp);
    }

    @Override
    public ResponseResult getMedicineSourceList(Integer pageNum, Integer pageSize, String searchStr) {
        Page<MmsMedicineSource> page = new Page<>(pageNum, pageSize);
        QueryWrapper<MmsMedicineSource> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(searchStr)) {
            queryWrapper.lambda().and(wrapper -> {
                wrapper.like(MmsMedicineSource::getSourceTitle, searchStr)
                        .or()
                        .like(MmsMedicineSource::getSourceAuthor, searchStr);
            });
        }
        queryWrapper.lambda().orderByDesc(MmsMedicineSource::getCreateTime);
        mmsMedicineSourceMapper.selectPage(page, queryWrapper);

        List<MmsMedicineSourceResp> list = page.getRecords()
                .stream()
                .map(mmsMedicineSource -> {
                    MmsMedicineSourceResp medicineSourceResp = new MmsMedicineSourceResp();
                    BeanUtils.copyProperties(mmsMedicineSource, medicineSourceResp);

                    MmsUser sourceOperatorUser = mmsUserMapper.selectById(medicineSourceResp.getSourceOperator());
                    if (sourceOperatorUser != null) {
                        UserinfoResp userinfoResp = new UserinfoResp();
                        BeanUtils.copyProperties(sourceOperatorUser, userinfoResp);
                        medicineSourceResp.setOperatorUserinfo(userinfoResp);
                    }

                    MmsUser lastUser = mmsUserMapper.selectById(medicineSourceResp.getLastUpdateUser());
                    if (lastUser != null) {
                        UserinfoResp userinfoResp = new UserinfoResp();
                        BeanUtils.copyProperties(lastUser, userinfoResp);
                        medicineSourceResp.setLastUserinfo(userinfoResp);
                    }

                    if (!isNullOrEmpty(mmsMedicineSource.getClassificationId())) {
                        MmsMedicineSourceClassification classification = mmsMedicineSourceClassificationMapper.selectById(mmsMedicineSource.getClassificationId());
                        if (classification != null) {
                            medicineSourceResp.setClassificationName(classification.getClassificationName());
                        }
                    }

                    return medicineSourceResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(list, total);
    }

    @Override
    @Transactional
    public ResponseResult updateMedicineSource(MmsMedicineSourceReq sourceReq, String user_id) {
        if (isNullOrEmpty(sourceReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        MmsMedicineSource mmsMedicineSource = mmsMedicineSourceMapper.selectById(sourceReq.getId());
        if (mmsMedicineSource == null) {
            return CommonResult.failed(CommonCodeEnum.MEDICINE_SOURCE_NOT_EXIST);
        }

        MmsMedicineSource updateSource = new MmsMedicineSource();
        BeanUtils.copyProperties(sourceReq, updateSource);
        updateSource.setLastUpdateUser(user_id);
        mmsMedicineSourceMapper.updateById(updateSource);
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deleteMedicineSource(MmsMedicineSourceReq sourceReq, String user_id) {
        if (isNullOrEmpty(sourceReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        MmsMedicineSource mmsMedicineSource = mmsMedicineSourceMapper.selectById(sourceReq.getId());
        if (mmsMedicineSource == null) {
            return CommonResult.failed(CommonCodeEnum.MEDICINE_SOURCE_NOT_EXIST);
        }

        mmsMedicineSource.setLastUpdateUser(user_id);
        mmsMedicineSourceMapper.updateById(mmsMedicineSource);

        mmsMedicineSourceMapper.deleteById(sourceReq.getId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult appDisplayMedicineSource(Integer pageNum, Integer pageSize) {
        QueryWrapper<MmsMedicineSourceClassification> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .orderByDesc(MmsMedicineSourceClassification::getClassificationTop)
                .orderByAsc(MmsMedicineSourceClassification::getClassificationSort);

        Page<MmsMedicineSourceClassification> page = new Page<>(pageNum, pageSize);
        mmsMedicineSourceClassificationMapper.selectPage(page, queryWrapper);

        List<MmsMedicineSourceClassificationDisplayResp> list = page.getRecords()
                .stream()
                .map(classification -> {
                    MmsMedicineSourceClassificationDisplayResp classificationResp = new MmsMedicineSourceClassificationDisplayResp();
                    BeanUtils.copyProperties(classification, classificationResp);

                    Page<MmsMedicineSource> sourcePage = new Page<>(1, 3);
                    List<MmsMedicineSourceDisplayResp> sourceRespList = mmsMedicineSourceMapper.selectPage(sourcePage, new LambdaQueryWrapper<MmsMedicineSource>()
                                    .eq(MmsMedicineSource::getClassificationId, classification.getId()))
                            .getRecords()
                            .stream()
                            .map(medicineSource -> {
                                MmsMedicineSourceDisplayResp medicineSourceResp = new MmsMedicineSourceDisplayResp();
                                BeanUtils.copyProperties(medicineSource, medicineSourceResp);
                                medicineSourceResp.setClassificationName(classification.getClassificationName());
                                return medicineSourceResp;
                            })
                            .collect(Collectors.toList());
                    classificationResp.setMedicineSourceList(sourceRespList);
                    return classificationResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(list, total);
    }
}
